home *** CD-ROM | disk | FTP | other *** search
- /*
- File: CVideoOutput.cpp
-
- Description: SimpleVideoOut is an example of using QuickTimes FireWire video
- output component to play a DV stream (.dv movie) out to a DV Camera.
- This code is based on VidOutApp originally written by Jay Lloyd, Casey King
- and Adrienne Wang.
-
- Author: era
-
- Copyright: © Copyright 2000 Apple Computer, Inc. All rights reserved.
-
- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
- ("Apple") in consideration of your agreement to the following terms, and your
- use, installation, modification or redistribution of this Apple software
- constitutes acceptance of these terms. If you do not agree with these terms,
- please do not use, install, modify or redistribute this Apple software.
-
- In consideration of your agreement to abide by the following terms, and subject
- to these terms, Apple grants you a personal, non-exclusive license, under Apple’s
- copyrights in this original Apple software (the "Apple Software"), to use,
- reproduce, modify and redistribute the Apple Software, with or without
- modifications, in source and/or binary forms; provided that if you redistribute
- the Apple Software in its entirety and without modifications, you must retain
- this notice and the following text and disclaimers in all such redistributions of
- the Apple Software. Neither the name, trademarks, service marks or logos of
- Apple Computer, Inc. may be used to endorse or promote products derived from the
- Apple Software without specific prior written permission from Apple. Except as
- expressly stated in this notice, no other rights or licenses, express or implied,
- are granted by Apple herein, including but not limited to any patent rights that
- may be infringed by your derivative works or by other works in which the Apple
- Software may be incorporated.
-
- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- COMBINATION WITH YOUR PRODUCTS.
-
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- Change History (most recent first): <1> 1/28/00 initial release
-
- */
-
- #include "CVideoOutput.h"
-
- using namespace dts;
-
- /* The CVideoOutput Class is very easy to use and encapsulates the basic set of functions required
- to output a DV Stream over FireWire.
-
- To instantiate a CVideoOutput object pass it your Movie.
- */
- CVideoOutput::CVideoOutput( const Movie inMovie ) : mMovie(NULL), mVOutputGWorld(NULL), mVOutputComponent(0), mVOutputInstance(NULL),
- mDefaultSoundOutComponent(NULL), mSoundOutComponent(NULL), mMovieClockInstance(NULL),
- mNumberAudioTracks(0), mVideoOutputInUse(false), rc(noErr)
- {
- ComponentDescription theVideoOutDesc;
-
- for ( UInt8 i = 0; i < kMaxAudioTrax; i++) {
- mAudioMediaHandler[i] = NULL;
- }
-
- if ( inMovie == NULL ) {
- rc = paramErr;
- return;
- }
-
- mMovie = inMovie;
-
- // Find the first FireWire output component
- theVideoOutDesc.componentType = QTVideoOutputComponentType;
- theVideoOutDesc.componentSubType = kFireCodecType;
- theVideoOutDesc.componentManufacturer = 0;
- theVideoOutDesc.componentFlags = 0L;
- theVideoOutDesc.componentFlagsMask = kQTVideoOutputDontDisplayToUser;
-
- mVOutputComponent = ::FindNextComponent( mVOutputComponent, &theVideoOutDesc );
- if ( mVOutputComponent == 0 )
- rc = badComponentType;
- }
-
- /* Open( const unsigned char inClientNameStr[], const short inMode )
- Opens the FireWire video output component, registers a client name with the component
- and sets up the display mode. This method also acquires the audio media handlers for up to five
- audio tracks for use later when setting up the sound device and will automatically close
- a video output component if it's already open before re-instantiating a new one.
- */
- OSErr CVideoOutput::Open( const unsigned char inClientNameStr[], const short inMode )
- {
- if ( mVOutputComponent == NULL || rc != noErr )
- goto bail;
-
- // Close any open video out components
- if ( mVOutputInstance != NULL) {
- Close();
- }
-
- mVOutputInstance = ::OpenComponent( mVOutputComponent );
-
- if ( mVOutputInstance == NULL ) {
- rc = badComponentType;
- goto bail;
- }
-
- // Register your client name with the Video Output Component
- ::QTVideoOutputSetClientName( mVOutputInstance, inClientNameStr );
-
- // Set the display mode
- rc = ::QTVideoOutputSetDisplayMode( mVOutputInstance, inMode );
- if ( rc ) {
- Close();
- goto bail;
- }
-
- // Find out how many tracks the movie contains,
- // the for each track find out which contain a sound media type
- // and finally grab the media handler for those tracks
- long theTrackCount = ::GetMovieTrackCount( mMovie );
- for ( UInt8 i = 1; i < theTrackCount + 1; i++) {
- OSType aMediaType;
-
- Track aTrack = ::GetMovieIndTrack( mMovie, i );
- Media aMedia = ::GetTrackMedia( aTrack );
- ::GetMediaHandlerDescription( aMedia, &aMediaType, NULL, NULL );
-
- if ( aMediaType == SoundMediaType ) {
- mAudioMediaHandler[mNumberAudioTracks] = ::GetMediaHandler( aMedia );
- mNumberAudioTracks++;
- }
- }
-
- bail:
- return rc;
- }
-
- /* Close( void )
- Closes the component instance and zeros the object. It is also called by the objects destructor.
- */
- void CVideoOutput::Close( void )
- {
- if ( mVOutputInstance != NULL ) {
- End();
- ::CloseComponent( mVOutputInstance );
- }
-
- mVOutputInstance = NULL;
- mNumberAudioTracks = 0;
-
- for ( UInt8 i = 0; i < kMaxAudioTrax; i++) {
- mAudioMediaHandler[i] = NULL;
- }
- }
-
- /* Begin( Boolean inUseVOsdev = true, Boolean inUseVOClk = true )
- Gains exclusive access to the hardware, sets up the sound output and the clock component
- associated with the video output component. Begin also acquires the GWorld used by the video
- output component. Both the sound and clock parameters are set to 'true' by default.
- */
- OSErr CVideoOutput::Begin( Boolean inUseVOsdev, Boolean inUseVOClk )
- {
- if ( mVOutputInstance == NULL )
- return paramErr;
-
- if ( mVideoOutputInUse ) {
- rc = videoOutputInUseErr;
- goto bail;
- }
-
- // Get exclusive access to the video hardware
- rc = ::QTVideoOutputBegin( mVOutputInstance );
- if ( rc ) goto bail;
-
- mVideoOutputInUse = true;
-
- // Get the default sound out component
- for ( UInt8 i = 0;i < mNumberAudioTracks; i++ ) {
- rc = ::MediaGetSoundOutputComponent( mAudioMediaHandler[i], &mDefaultSoundOutComponent );
- if ( rc ) goto bail;
- }
-
- // Get the first sound output component associated with the video output component.
- rc = ::QTVideoOutputGetIndSoundOutput( mVOutputInstance, 1, &mSoundOutComponent );
- if ( rc == noErr ) {
- ::SoundComponentSetInfo( (ComponentInstance)mSoundOutComponent, NULL, siSampleRate, (void *)eAudioRate44khz );
- } else {
- goto bail;
- }
-
- // Get a pointer to the clock component associated with the video output component
- // This is used to synchronize video and sound for a movie to the rate of the display
- if ( inUseVOClk && ::ComponentFunctionImplemented( mVOutputInstance, kQTVideoOutputGetClockSelect ) ) {
- rc = ::QTVideoOutputGetClock( mVOutputInstance, &mMovieClockInstance );
- if ( rc ) goto bail;
- }
-
- // Set up the sound device
- SetSoundDevice( inUseVOsdev );
-
- // Get a pointer to the graphics world used by a video output component
- rc = ::QTVideoOutputGetGWorld( mVOutputInstance, &mVOutputGWorld );
- if ( rc ) goto bail;
-
- // Initially turn off the echo port
- rc = SetEchoPort( NULL );
-
- bail:
- return rc;
- }
-
- /* End( void )
- Relinquishes exclusive access to the hardware. Also called by Close().
- */
- void CVideoOutput::End( void )
- {
- if ( mVideoOutputInUse ) {
- // Because the video output component disposes of the instance of the clock component which was returned to us
- // by the QTVideoOutputGetClock call in the Begin() method, we need to reset the clock for the movie to the default clock
- // by calling SetMovieMasterClock with nil as the value of the clock component) before calling QTVideoOutputEnd()
- ::SetMovieMasterClock( mMovie, (Component)NULL, NULL );
- ::QTVideoOutputEnd( mVOutputInstance );
- mVideoOutputInUse = false;
- }
-
- // If the video output was in use, after the call to ::QTVideoOutputEnd() mVOutputGWorld is
- // no longer valid as the the video output component automatically disposes of the
- // graphics world. If you need to use the GWorld after calling End(), you can call
- // CVideoOutput::GetGWorld() again but ONLY after the next time you call Begin() or it
- // will return NULL.
- // Egon's important safty tip - You must not call DisposeGWorld to dispose of the
- // graphics world used by a video output component...that would be bad.
- mVOutputGWorld = NULL;
-
- mDefaultSoundOutComponent = NULL;
- mSoundOutComponent = NULL;
- mMovieClockInstance = NULL;
- }
-
- /* SetEchoPort( const CGrafPtr inEchoPort = NULL )
- Allows you to display video both on an external video display and in a window.
- Pass in a CGrafPtr to specify a window to display video sent to the device. When video
- is displayed in the window you specify, the video is displayed in the window and sent
- to the normal output of the video output device. SimpleVideoOut by default turns the
- EchoPort on but allows you to turn it off.
- */
- OSErr CVideoOutput::SetEchoPort( const CGrafPtr inEchoPort )
- {
- if ( mVOutputInstance == NULL )
- return paramErr;
-
- if ( ::ComponentFunctionImplemented( mVOutputInstance, kQTVideoOutputSetEchoPortSelect ) ) {
- if ( inEchoPort == NULL ) {
- // Turn off Echo Port
- rc = ::QTVideoOutputSetEchoPort( mVOutputInstance, (CGrafPtr)NULL );
- if ( rc == noErr ) {
- if ( mVideoOutputInUse )
- ::SetMovieGWorld( mMovie, mVOutputGWorld, NULL );
- }
- } else {
- // Set up Echo Port
- rc = ::QTVideoOutputSetEchoPort( mVOutputInstance, inEchoPort );
- if ( rc == noErr ) {
- if ( mVideoOutputInUse )
- ::SetMovieGWorld( mMovie, inEchoPort, NULL);
- }
- }
- } else {
- rc = badComponentSelector;
- }
-
- return rc;
- }
-
- /* SetSoundDevice( const Boolean inUseVOsdev = true )
- This call will turn on/off the use of the video output components sound device, by
- default SimpleVideoOut turns it on. Passing in 'true' will set up the use of the
- video output components sound device and also sets up the clock component which is used
- to synchronize video and sound for a movie to the rate of the display. Passing in 'false'
- will use the default sound device and default clock.
- */
- OSErr CVideoOutput::SetSoundDevice( Boolean inUseVOsdev )
- {
- if ( mVOutputInstance == NULL )
- return paramErr;
-
- if ( inUseVOsdev == true ) {
- for ( UInt8 i = 0;i < mNumberAudioTracks; i++ ) {
- rc = ::MediaSetSoundOutputComponent( mAudioMediaHandler[i], mSoundOutComponent );
- if ( rc ) goto bail;
- }
- } else {
- for ( UInt8 i = 0;i < mNumberAudioTracks; i++ ) {
- rc = ::MediaSetSoundOutputComponent( mAudioMediaHandler[i], mDefaultSoundOutComponent );
- if( rc ) goto bail;
- }
- }
-
- // Setting the movie master clock to the video output clock needs to be called
- // after setting up the sound or it's gets spanked back to the default clock
- if ( mMovieClockInstance ) {
- if ( inUseVOsdev == true ) {
- ::SetMovieMasterClock( mMovie, (Component)mMovieClockInstance, NULL );
- } else {
- ::SetMovieMasterClock( mMovie, (Component)NULL, NULL );
- }
- }
-
- bail:
- return rc;
- }